package com.tenebrous.jestic.service.server;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.rain.ops.sdk.dto.ApiResult;
import com.rain.ops.sdk.utils.UUIDUtils;
import com.tenebrous.jestic.auth.AuthTokenGenerator;
import com.tenebrous.jestic.compents.exception.BizException;
import com.tenebrous.jestic.context.JesticContext;
import com.tenebrous.jestic.context.JesticTask;
import com.tenebrous.jestic.context.Response;
import com.tenebrous.jestic.entity.dto.EncryptionDto;
import com.tenebrous.jestic.entity.dto.TokenDto;
import com.tenebrous.jestic.entity.framwork.meber.organ.OrgUser;
import com.tenebrous.jestic.entity.model.request.DecryptionRequest;
import com.tenebrous.jestic.entity.model.request.JesticAuthorityRequest;
import com.tenebrous.jestic.entity.model.request.ServerHearBeatRequest;
import com.tenebrous.jestic.entity.model.response.JesticAuthorityResponse;
import com.tenebrous.jestic.entity.model.response.ServerHearBeatResponse;
import com.tenebrous.jestic.entity.server.JesticServer;
import com.tenebrous.jestic.enums.TaskEnum;
import com.tenebrous.jestic.factorys.JesticPropertyChainFactory;
import com.tenebrous.jestic.mapper.idao.server.JesticServerMapper;
import com.tenebrous.jestic.server.AbstractInstanceContext;
import com.tenebrous.jestic.server.Instance;
import com.tenebrous.jestic.service.SuperService;
import com.tenebrous.jestic.utils.JesticContextInstance;
import com.zy.tenebrous.jestic.utils.AESCodec;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Description:
 * @Project: jestic-server
 * @Package: com.tenebrous.jestic.service.server
 * @Author: zhangya
 * @CreateTime: 2023-06-02  15:44
 * @Version: 1.0.0
 */
@Slf4j
@Service
public class AuthServerService extends SuperService<JesticServer> {

    @Autowired
    private JesticServerMapper mapper;

    @Resource
    private AbstractInstanceContext abstractInstanceContext;

    @Resource
    private AuthTokenGenerator authToken;

    @Resource
    private AuthServerService authServerService;

    @Resource
    private JesticPropertyChainFactory<? extends JesticTask, ? extends Response> jesticPropertyChainFactory;

    @Autowired
    @Override
    protected void setSuperMapper() {
        super.setSuperMapper(this.mapper);
    }


    public void createServer(OrgUser currentUser, JesticServer jesticServer) {
        List<JesticServer> servers = mapper.selectByName(jesticServer.getServerName());
        List<JesticServer> jesticServers = servers.stream().filter(x -> x.getEnv().equals(jesticServer.getEnv())).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(jesticServers)) {
            throw new BizException("该服务已存在！请勿重复添加！");
        }
        try {
            jesticServer.setId(UUIDUtils.randomUUID());
            jesticServer.setServerKey(AESCodec.initkey());
            jesticServer.setServerSign(UUIDUtils.randomUUID());
            jesticServer.setServerStatus(0);
//            jesticServer.setCreateUserid(currentUser.getId());
            jesticServer.setCreateDate(new Date());
//            jesticServer.setCreateUsername(currentUser.getUsername());
            jesticServer.setDstate(0);
            mapper.insert(jesticServer);
        } catch (Exception e) {
            throw new BizException("生成密钥异常：", e);
        }
    }

    public static void main(String[] args) throws Exception {
        System.out.println(UUIDUtils.randomUUID());
        System.out.println(UUIDUtils.randomUUID());
        System.out.println(AESCodec.initkey());
    }

    public JesticServer selectServer(String serverId, String serverName) {
        return mapper.selectServer(serverId, serverName);
    }

    public String encryption(OrgUser currentUser, EncryptionDto dto) {
        List<JesticServer> servers = mapper.selectByName(dto.getServerName());
        JesticServer jesticServers = servers.stream().filter(x -> x.getEnv().equals(dto.getEnv())).findFirst().orElse(null);
        if (Objects.isNull(jesticServers)) {
            throw new BizException("该服务不存在！");
        }
        try {
            return AESCodec.encrypt(dto.getPwd(), jesticServers.getServerKey());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public PageInfo serverListByPage(int pageIndex, int pageSize, String serverName, String env, Integer serverStatus) {
        return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> this.mapper.selectByCondition(serverName, env, serverStatus));
    }

    public List<Instance> instanceList(String instanceId, String serverName, Integer env) {
        return abstractInstanceContext.getInstance();
    }

    public ApiResult<JesticAuthorityResponse> authority(JesticAuthorityRequest request) {
        log.info("jestic [ServerServiceGrpcImpl.authority] server [{}] successfully established connection， request \n[{}]", request.getServerName(), JSON.toJSONString(request, true));

        // 构建上下文对象
        JesticContext<JesticAuthorityRequest, JesticAuthorityResponse> context = JesticContextInstance.initContext(request, new JesticAuthorityResponse(),TaskEnum.AUTHORITY);
        jesticPropertyChainFactory.getHandler(TaskEnum.AUTHORITY.getCode()).handler(context);
        JesticAuthorityResponse contextResponse = context.getResponse();

        if (contextResponse.getCode() != 200) {
            return new ApiResult<JesticAuthorityResponse>(500, contextResponse.getMessage());
        } else {
            return new ApiResult<JesticAuthorityResponse>(200, "success", contextResponse);
        }

//        AbstractResponse<JesticAuthorityResponse> response = new AbstractResponse<>();
//        response.buildSuccess(context.getResponse());
//
//        String serverId = request.getServerId();
//        String serverName = request.getServerName();
//
//        // 查询服务
//        JesticServer jesticServer = authServerService.selectServer(serverId, serverName);
//        if (Objects.isNull(jesticServer)) {
//            log.info("jestic [ServerServiceGrpcImpl.authority] client [{}] server not found", request.getServerName());
//            return new ApiResult<JesticAuthorityResponse>(500, "server not found");
//        } else if (jesticServer.getServerStatus() != 1) {
//            log.info("jestic [ServerServiceGrpcImpl.authority] client [{}] status  not abnormal", request.getServerName());
//            return new ApiResult<JesticAuthorityResponse>(500, "server status not is running");
//        } else {
//            Instance instance = new ServerInstance(abstractInstanceContext.initContext(jesticServer, authToken)).initInstance();
//            log.info("jestic [ServerServiceGrpcImpl.authority] client [{}] init instance:[{}]", request.getServerName(), instance.getInstanceId());
//            // 设置客户端信息
//            instance.setIp(request.getIp());
//            instance.setPort(request.getPort());
//            instance.setGrpcPort(request.getGrpcPort());
//            instance.setInstanceStatus(InstanceStatusEnum.HEALTHY);
//            abstractInstanceContext.flushInstance(instance);
//            // 给与响应
//
//            JesticAuthorityResponse response = new JesticAuthorityResponse();
//            response.setId(request.getServerId());
//            response.setInstanceId(instance.getInstanceId());
//            response.setInstanceStatus(instance.getInstanceStatus().getCode());
//            response.setToken(instance.getToken());
//            response.setExpire(instance.getExpireTime());
//            response.setIsAuth(true);
//
//            // 提示信息
//            return new ApiResult<JesticAuthorityResponse>(200, "success", response);
    }


    public ApiResult<String> decrypt(DecryptionRequest request, String token, String instanceId) {
        log.info("\nSechubCryptographyImpl.decryption.request:\n{}", JSON.toJSONString(request, true));
        TokenDto tokenDto = authToken.checkToken(instanceId, token);
        if (Objects.isNull(tokenDto) || !tokenDto.isToken()) {
            return new ApiResult<>(500, "jestic AES decrypt fail:" + tokenDto.getMessage());
        }
        JesticServer jesticServer = authServerService.selectServer(request.getServerId(), request.getServerName());
        try {
            String encode = AESCodec.decrypt(request.getPwd(), jesticServer.getServerKey());
            return new ApiResult<>(200, "success", encode);
        } catch (Exception e) {
            log.error("JESTIC AES decrypt fail:[{}]", e.getMessage());
            return new ApiResult<>(500, "jestic AES decrypt fail:" + e.getMessage());
        }
    }

    public ApiResult<Boolean> heartBeat(ServerHearBeatRequest request, String token, String instanceId) {
        log.info("jestic [ServerServiceGrpcImpl.keepHeartBeat] recevie new hear beat by [{}]， instance:[{}]", request.getServerName(), request.getInstanceId());
        // 构建上下文对象
        JesticContext<ServerHearBeatRequest, ServerHearBeatResponse> context = JesticContextInstance.initContext(request, new ServerHearBeatResponse(),TaskEnum.HEART_BEAT);
        jesticPropertyChainFactory.getHandler(TaskEnum.HEART_BEAT.getCode()).handler(context);
        ServerHearBeatResponse contextResponse = context.getResponse();

        return new ApiResult<Boolean>(contextResponse.getCode(), contextResponse.getMessage(), contextResponse.isResult());

    }
}
